package br.unifor.cct.mia.evolutionary;

import br.unifor.cct.mia.util.Configurations;
import br.unifor.cct.mia.util.Methods;

public class Particula extends Individual {

	private static final long serialVersionUID = 114155934464639372L;

	private Individual pBest;	
	private int size;
	
	private double upper[];
	private double lower[];	
	private double position[];
	private double velocity[];
	
	public Particula(Configurations c) {
		this.configurations = c;
		this.size = c.getNvars();
		
		position = new double[size];
		velocity = new double[size];		
		lower = new double[size];
		upper = new double[size];
	}
	
	public double[] getVelocity() {
		return velocity;
	}
	public void setVelocity(double[] velocity) {
		this.velocity = velocity;
	}
	public int getSize() {
		return size;
	}
	public Individual getPBest() {
		return pBest;
	}
	public void setPBest(Individual best) {
		pBest = best;
	}
	public double[] getBestPosition() {
		return ((Particula)pBest).getPosition();
	}
	public double[] getPosition() {
		return position;
	}
	public void setPosition(double[] position) {
		this.position = position;
	}

	@Override
	public Object clone() {
		Particula result = new Particula(configurations);
		result.setFitness(this.getFitness());
		result.setSpeciesCount(this.getSpeciesCount());
		result.setSelectProbability(this.getSelectProbability());
		result.setLower(this.getLower());
		result.setUpper(this.getUpper());
	    System.arraycopy(this.getPosition(),0,result.getPosition(),0,this.getPosition().length);
	    System.arraycopy(this.getVelocity(),0,result.getVelocity(),0,this.getVelocity().length);
	    result.setPBest(this.getPBest());
		return result;
	}
	
	@Override
	public String toString() {
		StringBuffer result = new StringBuffer();
		result.append("Fitness: ");
		result.append(fitness);
		result.append("\n");
		
		result.append("[");
		for( int i=0; i<position.length; i++) {
			result.append(position[i]);
			result.append(",");
		}
		result.append("]\n\n");		
		
		return result.toString();
	}
	
    public void setLower(double[] lower) {
        this.lower = lower;
    }
    public void setLower(double lower, int pos) {
        this.lower[pos] = lower;
    }
    public double[] getLower() {
        return this.lower;
    }
    public double getLower(int pos) {
        return this.lower[pos];
    }    
	public void setUpper(double[] upper) {
        this.upper = upper;
    }
    public void setUpper(double upper, int pos) {
        this.upper[pos] = upper;
    }
    public double[] getUpper() {
        return this.upper;
    }
    public double getUpper(int pos) {
        return this.upper[pos];
    }
    
	public int hashCode() {
		int hashCode = 0;
		int atual = 3;
		for ( int i=0; i<position.length; i++ ) {
			hashCode += position[i]*Methods.gerarPrimo(atual);
			atual++;
		}		
		return hashCode;
	}
	
	public boolean equals(Object arg0) {
		Particula gen = (Particula)arg0;

		for ( int i=0; i<lower.length; i++ ) {
			if ( gen.getLower()[i] != lower[i] ) 
				return false;
		}
		
		for ( int i=0; i<upper.length; i++ ) {
			if ( gen.getUpper()[i] != upper[i] ) 
				return false;
		}
		
		for ( int i=0; i<velocity.length; i++ ) {
			if ( gen.getVelocity()[i] != velocity[i] ) 
				return false;
		}
		
		for ( int i=0; i<position.length; i++ ) {
			if ( gen.getPosition()[i] != position[i] ) 
				return false;
		}
		return true;
	}
}
